home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / pmode / 386p_099 / 386video.asm < prev    next >
Encoding:
Assembly Source File  |  1994-05-02  |  33.2 KB  |  1,149 lines

  1. include 386power.inc
  2. include 386video.inc
  3.  
  4. ; BASIC VIDEO SERVICES
  5. ; _SetGameMode
  6. ; _RestoreTextMode
  7. ; _WaitVR
  8. ; _DisplayStart
  9. ; _PageFlip
  10.  
  11. code32 segment para public use32
  12.        assume cs:code32,ds:code32
  13.        
  14. _ActiveBase dd 0 ;base of page to write to
  15.  MidBase    dd 0 ;base of "in between" page
  16. _ViewBase   dd 0 ;base of page to show
  17. _ScoBase    dd 0 ;base of "scoreboard" panel
  18.  
  19. ; index of row start offsets from base of display screen (active,view,score)
  20. _RowStart   dd 0
  21.             dd VYHEIGHT dup(0)
  22.  
  23. ; sottrai VGARAWOFFSET per passare da pointer code32 relativo
  24. ; ad offset nella vga memory window
  25. VGARAWOFFSET dd 0
  26.  
  27.   DispOffset      dd 0  ; offset di scrolling
  28. ; old code for pix panning  
  29. ; SmoothPix       dd 0  ; valore per smooth scrolling
  30.  
  31. ; XVGA MODE ENTRY/EXIT ROUTINES
  32.  
  33. ;----------------------------------------------------------------------------
  34. ; void SetGameMode;
  35. ;
  36.              public _SetGameMode
  37. _SetGameMode:
  38.              
  39.                 pushad
  40.                 
  41.  
  42.                 mov V86ax,0013h    ; set 256-color mode BIOS MODE 13h
  43.                 mov al,10h         ;
  44.                 int 33h            ;
  45.  
  46.         mov dx,SEQUENCER    ; convert to X-mode addressing
  47.                 ; sequencer register 04h (MEMORY MODE)
  48.                 ; set chain mode off,no odd/even,more than 64k,graphics mode
  49.                 mov ax,0604h        ;
  50.                 out dx,ax           ;
  51.                 
  52.                 WRITEMODE  WPUT
  53.                 WRITEPLANE WPA
  54.  
  55.                 @rlp edi,000A0000h
  56.                 mov  ecx,16*1024     ; CLEAR VIDEO MEMORY
  57.                 xor  eax,eax         ; (addressing mode is planar
  58.                 rep stosd            ;  but raster scanning is still the
  59.                                      ;  same of mode 13h)
  60.                                      
  61.                 ; now change the raster scanning method
  62.         mov dx,CRTC
  63.  
  64.                 mov ax,00014h       ; TURN OFF DWORD MODE (CRTC LONG MODE)
  65.                 out dx,ax           ; (change vram scanning method)
  66.  
  67.                 mov ax,0E317h       ; TURN ON BYTE MODE
  68.                 out dx,ax           ;
  69.                 
  70.                 ; Tweaked mode fully activated, now perform other stuff
  71.                 
  72.         mov al,LINE_OFS
  73.                 mov ah,SXWIDTH ; ampiezza di una linea/8
  74.                 out dx,ax
  75.                 
  76.                 ;mov dx,GRAPHICS   ; superfluo se non sei paranoide
  77.                 ;mov ax,ALL_BIT
  78.                 ;out dx,ax
  79.                 
  80.  
  81.  
  82. ; inizializza variabili "interne" ed "esterne"
  83.                 @rlp  eax,0A0000h
  84.                 mov VGARAWOFFSET,eax
  85.                 @rlp eax,SCOBASE
  86.                 mov _ScoBase,eax
  87.                 @rlp eax,BASE0
  88.                 mov _ViewBase,eax
  89.                 @rlp eax,BASE1
  90.                 mov MidBase,eax
  91.                 @rlp eax,BASE2
  92.                 mov _ActiveBase,eax
  93. ;                xor eax,eax
  94.                  mov DispOffset,eax
  95. ;                mov SmoothPix,eax
  96.  
  97.                 mov edi,offset _RowStart  ; Row offset table 
  98.                 mov ecx,VYHEIGHT          ;
  99.                 mov eax,0                 ;
  100.                 mov ebx,PXWIDTH           ;
  101.  
  102. iloop:
  103.                 stosd
  104.                 add eax,ebx
  105.         loop iloop
  106.                 
  107.                 mov ecx,LYHEIGHT
  108.                 call SplitScreen
  109.                 call InstallPFLP
  110.                 call _PageFlip
  111. ; ritorna a chi ha chiamato
  112.                 popad
  113.         ret
  114.         
  115. ;----------------------------------------------------------------------------
  116. ; void RestoreTextMode( void )
  117.  
  118.         public  _RestoreTextMode
  119. _RestoreTextMode:
  120.                 mov  V86ax,0003h        ; set text mode
  121.                 mov al,10h
  122.                 int 33h
  123.         ret
  124.  
  125.  
  126.  
  127. ;----------------------------------------------------------------------------
  128. ; void _WaitVR(void)    WAIT A FULL V.R TIME FRAME
  129. ;
  130.  
  131.         public _WaitVR
  132. _WaitVR:        push edx
  133.                 push eax
  134.         mov     dx,STATUS
  135. @@swap_retr1:   cli
  136.         in      al,dx
  137.         test    al,8  ; VERTICAL RETRACE ?
  138.         jnz    @@swap_retr1  ; loop if V.R. (into retrace)
  139. @@swap_retr2:
  140.         in      al,dx
  141.         test    al,8  ; V.R. ?
  142.         jz    @@swap_retr2  ; loop if not V.R.
  143.                 sti
  144.                 pop eax
  145.                 pop edx
  146.         ; NOW you have a FULL V.R. time frame available
  147.         ret
  148.  
  149.  
  150.  
  151. ;----------------------------------------------------------------------------
  152. ; void DisplayStart(eax= x,edx =y)  SET DISPLAY VIDEO WINDOW POSITION
  153. ;                                   INSIDE DISPLAY PAGE
  154.  
  155.         public _DisplayStart
  156.  
  157. _DisplayStart:
  158.                 ; eax= x_position , ebx = y_position
  159.                 ;;push ecx
  160.                 push eax
  161.                 ;;mov ecx,eax        ;
  162.                 ;;and ecx,3          ; maschera di bits per lo shifter
  163.                 ;;shl ecx,1          ;
  164.                 ;;mov SmoothPix,ecx  ;
  165.  
  166.                 shr eax,2                ;offset nella pagina video corrente
  167.                 add eax,_RowStart[edx*4] ;
  168.                 mov DispOffset,eax       ;
  169.                 pop eax
  170.                 ;;pop ecx
  171.         ret
  172.  
  173.  
  174. ;----------------------------------------------------------------------------
  175. ; void DisplayPage(ECX= offset of display page )  
  176. ; SHOW PAGE starting at offset eax  (INTERNAL FUNCTION)
  177.  
  178. DisplayPage:
  179.                 ; ecx = offset di inizio pagina video corrente
  180.                 mov     bx,VSTART_HILO   ;preload for fastest access
  181.                 add     ecx,DispOffset   ;  somma l' inizio video nella pagina
  182.                 sub     ecx,VGARAWOFFSET ; trasforma in raw vga offset
  183.                 xchg    bh,cl    ; BX=prima coppia CX=seconda coppia
  184.  
  185.         mov     dx,STATUS
  186.  
  187.         cli
  188. ;@@WaitNVS:
  189. ;                in      al,dx
  190. ;                and     al,08h
  191. ;                jnz     @@WaitNVS  ;vertical sync is active high (0= drawing)
  192. @@WaitHS:
  193.                 in      al,dx
  194.                 and     al,01
  195.                 jnz     @@WaitHS  ;hor. sync is active high (1 = active)
  196.                 ; n.b. HSync is display enable too!!!
  197.                 
  198.         ; Set the start offset in display memory of the page to display.
  199.         mov     dx,CRTC
  200.                 mov     eax,ebx
  201.         out     dx,ax   ;start address low
  202.                 mov     eax,ecx
  203.         out     dx,ax   ;start address high
  204.  
  205. ;                mov dx,STATUS
  206. ;@@WaitVS:
  207. ;                in      al,dx
  208. ;                and     al,08h
  209. ;                jz     @@WaitVS  ;vertical sync is active high (1 = active)
  210. ;@@QuickFlip:
  211. ;                ; attribute controller already in address mode
  212. ;                mov     dx,ATTRIBUTE
  213. ;                mov     al,PEL_PANNING
  214. ;                out     dx,al
  215. ;                mov     al,byte ptr SmoothPix
  216. ;                
  217. ;                ; now give some time to old jerky vga cards
  218. ;                jc  zik
  219. ;                zik:
  220. ;                jnc zok
  221. ;                zok:
  222. ;                jc  zik2
  223. ;                zik2:
  224. ;                jnc zok2
  225. ;                zok2:
  226. ;                jc  zik3
  227. ;                zik3:
  228. ;                jnc zok3
  229. ;                zok3:
  230.                 
  231.         out     dx,al
  232.         sti
  233.                 
  234.         ret
  235.  
  236. ;--------------------------------------------------------------------------
  237. ; void cdecl PageFlip(void)
  238. ;
  239.       public _PageFlip
  240.  
  241. _PageFlip: ; _Viewbase <-- _ActiveBase <-- MidBase <-- _ViewBase
  242.            ; & show new _ViewBase
  243.           pushad
  244.           mov ebx,PageTicks
  245. @pfgloop:
  246.           mov eax,_TimerTicks
  247.           mov edx,eax
  248.           sub eax,ebx
  249.           cmp eax,FrameTicks
  250.           jb @pfgloop   ; loop if too few time has passed
  251.           mov PageTicks,edx          
  252.           
  253.           mov  eax,MidBase
  254.           mov  ebx,_ViewBase
  255.           mov  ecx,_ActiveBase
  256.           mov  _ActiveBase,eax
  257.           mov      MidBase,ebx
  258.           mov    _ViewBase,ecx
  259.           ; ecx == new viewbase
  260.       call DisplayPage
  261.           popad
  262.       ret
  263.  
  264. ;--------------------------------------------------------------------------
  265. ; void cdecl SplitScreen(ecx = Splitline)
  266. ; INTERNAL FUNCTION
  267.  
  268. SplitScreen:
  269.         ; ecx = SplitLine (in low word)
  270.  
  271.     ; inanzitutto disabilita il panning
  272.         ; dello splitscreen, ma prima salva il parametro
  273.         push ecx
  274.         cli
  275.  
  276.         mov dx,STATUS ;poni attribute controller in address mode
  277.         in al,dx
  278.         
  279.         mov ecx,200
  280. okuto1: loop okuto1
  281.  
  282.     ; ora disabilita il panning dello splitscreen
  283.         mov al,ATTR_CONTROL
  284.         mov dx,ATTRIBUTE
  285.         out dx,al          ; seleziona registro di panning
  286.         
  287.         ; lascia passare del tempo
  288.         mov ecx,200
  289. okuto2: loop okuto2
  290.         
  291.         inc dx
  292.         in al,dx ;leggi gli attributi correnti
  293.         or al,NOSPLITPAN
  294.         
  295.         ; lascia passare del tempo
  296.         mov ecx,200
  297. okuto3: loop okuto3
  298.  
  299.         mov ah,al ; salva i flag
  300.         
  301.         mov dx,STATUS ;
  302.         in al,dx      ; nuovamente in address mode (ripulisci il f/f di stato)
  303.         
  304.         mov dx,ATTRIBUTE
  305.         mov al,ATTR_CONTROL ;pronto a ri-scrivere su attribute controller
  306.         out dx,al
  307.         
  308.         ; lascia passare del tempo
  309.         mov ecx,200
  310. okuto4: loop okuto4        
  311.  
  312.         mov al,ah   ; scrivi i nuovi flag degli attributi video
  313.         out dx,al   ;
  314.  
  315.         sti
  316.  
  317.     ; ora puoi modificare il line compare
  318.     ; register e gli altri suoi bits
  319.     ; sparsi in altri 2 registri
  320.         pop ecx
  321.     ; Now wait for vertical sync, so the other page will be invisible when
  322.     ; we start drawing to it.
  323.     mov     dx,STATUS
  324.         cli
  325. @@WVS:
  326.     in      al,dx
  327.         and     al,08h
  328.     jz      @@WVS  ;vertical sync is active high (1 = active)
  329.  
  330.     mov dx,CRTC
  331.         
  332.         ;  ECX = splitline
  333.         
  334.         shl ecx,1  ; moltiplica per due
  335.                    ; (si e' in modo a doppia scansione)
  336.         dec ecx    ; e riduci di 1
  337.  
  338.     ; write bit 0..7
  339.     mov al,LINE_COMPARE
  340.         mov ah,cl
  341.         out dx,ax
  342.  
  343.     ; write bit 8
  344.  
  345.         mov cl,0
  346.  
  347.         shr ecx,1  ; porta il bit 8
  348.         shr  cl,3  ; nel bit 4 di BL
  349.  
  350.         mov ax,0707h  ;bit 8 is CRTC INDEX 7 BIT 4
  351.         out dx,al
  352.         inc dx
  353.         in al,dx
  354.         dec dx
  355.         and al,0EFh ;azzera bit 4
  356.         or al,cl  ; registra il nuovo bit
  357.         xchg ah,al
  358.         out dx,ax
  359.  
  360.         ; write bit 9
  361.         mov cl,0
  362.         shr ecx,1
  363.         shr cl,1
  364.         mov ax,0909h
  365.         out dx,al
  366.         inc dx
  367.         in al,dx
  368.         dec dx
  369.         and al,0BFh ;azzera bit 6
  370.         or  al,cl
  371.         xchg al,ah
  372.         out dx,ax
  373.  
  374.     sti ;enable interrupts
  375.     ret
  376.  
  377. ; EXTENDED INPUT, TIMER DRIVEN PAGE FLIPPING & SOUND OUTPUT
  378. ; questa sezione di 386VIDEO(game)
  379. ; gestisce in modo diretto la tastiera,lo speaker incorporato
  380. ; in ogni PC &  il timer connesso a IRQ0.
  381.  
  382.  
  383. ; RAW KEYBOARD I/O
  384. ; 32bit section, Keyboard ISR for raw keyboard input
  385.  
  386. ; Raw KeyBoard table
  387. ; Every key "description" is made of two consecutive bytes
  388. ; if a key has a keyboard scancode K
  389. ; address:     
  390. ; _RKB+(K)  bit   meaning:       description:
  391. ;             0   IS_PRESSED     0 == key K is currently not pressed
  392. ;                                1 == key K is currently     pressed
  393. ;
  394. ;             1   TOUCHED        0 == key K has not been pressed 
  395. ;                                     since last time you cleared this bit.
  396. ;                                1 == key K has been pressed
  397. ;
  398. ; Use IS_PRESSED for "raw" control (i.e cursor keys in a game)
  399. ; and TOUCHED (but clear it before!!) for "keyboard-like"  control
  400. ; when you have to choose items in a menu or when
  401. ; you have to check special "toggle" keys that may be pressed anytime
  402. ; (i.e. the all time high ESC key)    
  403.         public  _RKB,_RKBPressed
  404. _RKB    db      0    
  405.         db      128 dup(0)
  406.  
  407. _RKBPressed db  0 ; 0 == no keys pressed since last time you reset this flag
  408.                   ; 1 == something happened, a key has been pressed
  409.                   ; (this is like a "general" TOUCHED flag)
  410.  
  411. IRQ1_ISR:
  412.         cli
  413.         push    eax
  414.         push    ebx
  415.         push    ds
  416.         mov     ds,cs:_SelData
  417.  
  418.     in      al,60h          ; get scan code
  419.  
  420.         movzx   ebx,al          ; move scan code to index register
  421.  
  422.     in      al,61h          ; get control code
  423.         push    eax
  424.     or      al,80h          ; clear keyboard of interrupt:
  425.     out     61h,al          ;
  426.         pop     eax             ;   first send control byte with inverted MSB
  427.     out     61h,al          ;   then send plain control byte
  428.  
  429.         mov     al,EOI          ; send generic EOI to
  430.         out     PIC0_CTRL,al    ;   PIC
  431.                 ; enabling other interrupts
  432.         mov al,bl
  433.         and bl,07Fh
  434.     ; if the key was released, the high bit is set in the scan code
  435.         mov byte ptr[ebx+offset _RKB],02h ; reset "Is being pressed" flag
  436.                                           ; and left set "Has been pressed"
  437.         
  438.         rol al,1
  439.         jc  key_released
  440.         mov byte ptr [ebx+offset _RKB],03h ; set "Is being pressed" flag
  441.                                            ; and "Has been pressed" flag
  442. key_released:
  443.         mov _RKBPressed,1     ; state of keyboard has changed
  444.         sti
  445.         pop ds
  446.         pop ebx
  447.         pop eax
  448.         iretd 
  449.  
  450.         public _WaitKey
  451. _WaitKey:
  452.         ; WAITS UNTIL A KEY IS PRESSED
  453.         mov _RKBPressed,0
  454. @waitmore:        
  455.         test _RKBPressed,1
  456.         jz @waitmore        
  457.         ret
  458.         
  459.         public _InstallRKB
  460. _InstallRKB:
  461.         pushad
  462.         mov eax,0
  463.         mov edi,offset _RKB
  464.         mov ecx,32 ; 128bytes == 32 dwords
  465.         rep stosd
  466.         cli
  467.         test _386Man,IS_DPMI
  468.         jnz NoReflex
  469.         mov al,21h
  470.         mov V86ax,2509h
  471.         mov V86ds,seg code16
  472.         mov V86dx,offset IRQ1_RISR
  473.         int 33h
  474. NoReflex:        
  475.         mov bl,1
  476.         mov edx,offset IRQ1_ISR
  477.         call _SetIRQ
  478.         sti
  479.         popad
  480.         ret
  481.  
  482. ; PWM SOUND ON PC-SPEAKER & TIMER-DRIVEN PAGE FLIPPING
  483. ; 32bit section
  484.  
  485.         public  _SoundOn,_SoundLen,_SoundPtr
  486.         public  _DSoundOn,_DSoundLen,_DSoundPtr
  487.         
  488.         align dword
  489. ; current sound data        
  490. _SoundLen   dd      0  ; default = zero sound lenght
  491. _SoundPtr   dd      0  ; default = null, points to already decode sound data
  492.                        ; the installed sound driver must play
  493. ; default sound data                       
  494. _DSoundLen  dd      0  ; default = zero , default sound lenght                                     
  495. _DSoundPtr  dd      0  ; default = null , default sound
  496.  
  497.          align byte
  498.          
  499. _SoundOn  db 0 ; Set this to turn on sound generation, all sound driver must
  500.                ; refer to this flag to control sound output
  501. _DSoundOn db 0 ;ditto for the default sound insertion at end of sound
  502.                           
  503.  
  504.  Buzzing    db      0 ; are we currently producing sound ? (private var.)
  505.  
  506.           align dword
  507. ; decrementi di contatore usati come riferimento
  508. PWMTICK   = 149           ; conteggio equivalente a 8008Hz
  509. VSyncTick dd 0            ; Vsync count ... Initialize with VSyncInit()
  510. TIMERTICK = (64*1024)     ; conteggio equivalente a 18.2 Hz
  511. ONESECOND = 1193180
  512.  
  513.         public _TimerTicks,_SysTicks,_Seconds
  514.         
  515. _TimerTicks dd 0 ; ticks in frequenza base a 1193180 Hz
  516.                  ; usa sempre la granularita piu fine a disposizione
  517.                  
  518.  PageTicks  dd 0 ; tick counter for pageflips
  519.  FrameTicks  = 19886 ; 1193180hz/60hz timer count
  520.                  
  521.  InnerTicks dd 0 ; simile a _TimerTicks, ma usato per calcolare systicks
  522.  SecTicks   dd 0 ; idem, ma per _Seconds
  523.  
  524. _SysTicks dd 0  ; ticks a 18.2Hz      
  525. _Seconds  dd 0  ; contasecondi totali
  526.  
  527.          align byte
  528.  
  529. InstallPFLP:
  530.         ; installs the pageflip support code
  531.         pushad
  532.         cli
  533.         ; first in real mode
  534.         test _386Man,IS_DPMI
  535.         jnz @nopfreflex
  536.         mov al,21h
  537.         mov V86ax,2508h
  538.         mov V86ds,code16
  539.         mov V86dx,offset PFLP_RISR
  540.         int 33h
  541. @nopfreflex:        
  542.         ; second in protected mode (it works only this way under DPMI)
  543.         mov bl,0
  544.         mov edx,offset PFLP_ISR
  545.         call _SetIRQ
  546.         mov al,T_SET0   ; set programmable interval timer 0 to FrameTicks
  547.         out PIT_CTRL,al ;
  548.         mov eax,FrameTicks
  549.         out PIT0,al     ;
  550.         mov al,ah       ;
  551.         out PIT0,al     ;
  552.         ; initialize counters
  553.         mov _TimerTicks,0
  554.         mov PageTicks,0
  555.         mov InnerTicks,0
  556.         mov SecTicks,0
  557.         mov _SysTicks,0
  558.         mov _Seconds,0
  559.         sti
  560.         popad
  561.         ret         
  562.         
  563. PFLP_ISR: 
  564.         sti
  565.         push    eax
  566.         push    ebx
  567.         push    ds
  568.  
  569.         mov     ds,cs:_SelData
  570.         mov ebx,FrameTicks
  571.         add _TimerTicks,ebx
  572.         add  InnerTicks,ebx
  573.         add    SecTicks,ebx
  574.         mov eax,SecTicks
  575.         sub eax,ONESECOND
  576.         jb pdone_sec
  577.         mov SecTicks,eax
  578.         inc _Seconds
  579. pdone_sec:        
  580.         
  581.         mov eax,InnerTicks
  582.         sub eax,TIMERTICK
  583.         jb pdone_irq0
  584.         mov InnerTicks,eax
  585.         ; n.b. TTick conta i ticks di sistema in formato fixed point
  586.         ;      con una cifra decimale
  587.         inc _SysTicks
  588. pzapped_time:
  589.         ; it's time to call the old ISR
  590.         mov al,8
  591.         int 33h
  592.         jmp short pirq0_digged
  593. pdone_irq0:        
  594.         mov al,EOI
  595.         out PIC0_CTRL,al
  596. pirq0_digged:        
  597.         pop ds
  598.         pop ebx
  599.         pop eax
  600.         iretd ; ritorna il controllo a 386 power
  601.  
  602.         public _InstallPWM
  603. _InstallPWM:
  604.         ; install irqs & set up voc_table
  605.         pushad
  606.         ; initialize internal vars
  607.         mov Buzzing,0
  608.         mov _SoundOn,0
  609.         mov _DSoundOn,0
  610.         mov _SoundLen,0
  611.         mov _SoundPtr,0
  612.         mov _DSoundLen,0
  613.         mov _DSoundPtr,0
  614. ; set voc_table
  615.         mov esi,offset pwm_table
  616.         mov edi,offset voc_table
  617.         mov eax,0
  618.         mov ecx,64
  619. set_up_voc_table:        
  620.         movsd
  621.         loop set_up_voc_table
  622.         cli
  623.         ; first install the real mode side
  624.         cmp _386Man,IS_DPMI
  625.         je @nopwreflex
  626.         mov al,21h
  627.         mov V86ax,2508h
  628.         mov V86ds,code16
  629.         mov V86dx,offset code16:IRQ0_RISR
  630.         int 33h
  631. @nopwreflex:        
  632.         ; then the protected mode side (it works only this way in DPMI)
  633.         mov bl,0
  634.         mov edx,offset IRQ0_ISR
  635.         call _SetIRQ
  636.         mov ebx,F8008 ; 8008Hz count
  637.         cmp _386Man,IS_DPMI
  638.         jne @vcpispeed
  639.         shl ebx,1 ; freq to 4004Hz
  640. @vcpispeed:        
  641.         mov play_rate,ebx ; set playback frequency for voc converter
  642.         
  643.         mov al,T_SET0   ; set programmable interval timer 0 to 8008Hz or 4004Hz
  644.         out PIT_CTRL,al ;
  645.         mov al,bl       ;
  646.         out PIT0,al     ;
  647.         mov al,bh       ;
  648.         out PIT0,al     ;
  649.         
  650.         sti
  651.         ; no need to initialize time counters
  652.         ; InstallPFLP already did it
  653.         popad
  654.         ret         
  655.         
  656. ; PWM SOUND SPEAKER DRIVER
  657.  
  658.  zarp_sound:
  659.         cmp _DSoundOn,0
  660.         je dont_buzz
  661.         mov eax,_DSoundLen
  662.         dec eax
  663.         mov ebx,_DSoundPtr
  664.         mov _SoundLen,eax
  665.         jmp doit_again
  666.         
  667.  dont_buzz:
  668.         cmp Buzzing,0
  669.         je getoutsound
  670.         mov Buzzing,0
  671.         ; turn speaker OFF
  672.         in      al, 61h                 ;Read I/O port B into AL
  673.         and     al, 11111100b           ;mask lower two bits
  674.         out     61h, al                 ;to turn off speaker
  675.         jmp short getoutsound
  676.  
  677. DoTheSound macro
  678.         cmp _SoundOn,0
  679.         je  dont_buzz    ; no sound if sound flag is off
  680.         cmp _SoundLen,0
  681.         je  zarp_sound   ; no sound if at end of "soundtrack"
  682.         dec _SoundLen    ; decrease "soundtrack" lenght
  683.  
  684.         mov     ebx,_SoundPtr    ;get current count pointer
  685. doit_again:
  686.         mov     al,[ebx]            ; count into AX
  687.         inc     ebx                 ; & update sound pointer
  688.         mov     _SoundPtr,ebx       ; (only offset is changed)
  689.         mov     ah,al    ; copy count 
  690.         or      al,al         ; zero count sets speaker off
  691.         ;je      dont_buzz     ;
  692.         
  693.         mov     al,P_SET2S
  694.         out     PIT_CTRL,al      
  695.         mov     al,ah
  696.         out     PIT2, al             
  697.  
  698.         cmp Buzzing,0
  699.         jne getoutsound
  700.         mov Buzzing,1
  701.         ; turn sound on
  702.         in      al, 61h                 ;read I/O port B into AL
  703.         or      al,3                    ;turn on bits 0 and 1
  704.         out     61h,al                  ;to turn on speaker
  705. getoutsound:
  706.         endm
  707.  
  708. ; IRQ0 Timer handler, it handles TWO different "time driven" nested loops
  709. ; the 8008 Hz  PWM sound system
  710. ; the 18,2 Hz System tick for periodic events and rough time keeping
  711.  
  712. IRQ0_ISR: 
  713.         cli
  714.         push    eax
  715.         push    ebx
  716.         push    ecx
  717.         push    edx
  718.     push    ds
  719.  
  720.         mov     ds,cs:_SelData
  721.         mov ebx,play_rate
  722.         add _TimerTicks,ebx
  723.         add  InnerTicks,ebx
  724.         add    SecTicks,ebx
  725.         DoTheSound
  726.         sti
  727.         mov eax,SecTicks
  728.         sub eax,ONESECOND
  729.         jb done_sec
  730.         mov SecTicks,eax
  731.         inc _Seconds
  732. done_sec:        
  733.         
  734.         mov eax,InnerTicks
  735.         sub eax,TIMERTICK
  736.         jb done_irq0
  737.         mov InnerTicks,eax
  738.         ; n.b. TTick conta i ticks di sistema in formato fixed point
  739.         ;      con una cifra decimale
  740.         inc _SysTicks
  741. zapped_time:
  742.         ; it's time to call the old ISR
  743.         mov al,8
  744.         int 33h
  745.         jmp short irq0_digged
  746. done_irq0:        
  747.         mov al,EOI
  748.         out PIC0_CTRL,al
  749. irq0_digged:        
  750.         pop ds
  751.         pop edx
  752.         pop ecx
  753.         pop ebx
  754.         pop eax
  755.         iretd ; ritorna il controllo a 386 power
  756.         
  757. ;-----------------------------------------------------------------------------
  758. ; 8bit, not compressed VOC to "raw 8 bit pcm"
  759.           align dword
  760. voc_rate  dd ?
  761. play_rate dd ? ; playback sample rate and IRQ0 frequency under PWM sound
  762.  
  763.           align byte
  764. pwm_table db 1 , 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20
  765.           db 21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30
  766.           db 31,31,31,32,32,32,33,33,33,34,34,34,35,35,35,36,36,36,37,37          
  767.           db 37,38,38,38,39,39,39,40,40,40,41,41,41,42,42,42,43,43,43,44          
  768.           db 45,45,45,46,46,46,47,47,47,48,48,48,49,49,49,50,50,50,51,51
  769.           db 51,52,52,52,53,53,53,54,54,54,55,55,55,56,56,56,57,57,57,57
  770.           db 58,58,58,58,59,59,59,59,60,60,60,60,61,61,61,61,62,62,62,62          
  771.           db 63,63,63,63,63,64,64,64,64,64,65,65,65,65,65,66,66,66,66,66
  772.           db 67,67,67,67,67,68,68,68,68,68,69,69,69,69,69,70,70,70,70,70
  773.           db 71,71,71,71,71,71,71,71,71,71,72,72,72,72,72,72,72,72,72,72
  774.           db 73,73,73,73,73,73,73,73,73,73,74,74,74,74,74,74,74,74,74,74
  775.           db 75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75
  776.           db 75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75
  777.           
  778. voc_table db 1 , 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20
  779.           db 21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30
  780.           db 31,31,31,32,32,32,33,33,33,34,34,34,35,35,35,36,36,36,37,37          
  781.           db 37,38,38,38,39,39,39,40,40,40,41,41,41,42,42,42,43,43,43,44          
  782.           db 45,45,45,46,46,46,47,47,47,48,48,48,49,49,49,50,50,50,51,51
  783.           db 51,52,52,52,53,53,53,54,54,54,55,55,55,56,56,56,57,57,57,57
  784.           db 58,58,58,58,59,59,59,59,60,60,60,60,61,61,61,61,62,62,62,62          
  785.           db 63,63,63,63,63,64,64,64,64,64,65,65,65,65,65,66,66,66,66,66
  786.           db 67,67,67,67,67,68,68,68,68,68,69,69,69,69,69,70,70,70,70,70
  787.           db 71,71,71,71,71,71,71,71,71,71,72,72,72,72,72,72,72,72,72,72
  788.           db 73,73,73,73,73,73,73,73,73,73,74,74,74,74,74,74,74,74,74,74
  789.           db 75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75
  790.           db 75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75
  791.           
  792. set_comp macro
  793.            lodsb
  794.            or al,al
  795.            mov al,2 ; compressed data
  796.            jne voc_end
  797.          endm
  798.            
  799. set_sample macro
  800.              lodsb
  801.              and eax,0FFh
  802.              mov ebx,256
  803.              mov edx,0
  804.              mov eax,1000000
  805.              div ebx
  806.              ; eax = samples/sec
  807.              mov ebx,eax
  808.              mov edx,0
  809.              mov eax,1193180
  810.              div ebx
  811.              ; eax = timer count equivalent to sample rate
  812.              mov voc_rate,eax
  813.            endm
  814.            
  815. blitquiet macro
  816.             ; ecx =ctr
  817.             mov edx,0
  818.             mov ebx,voc_rate
  819.             mov ebp,play_rate
  820.             mov eax,0
  821. stamp:
  822.             dec ecx
  823.             je end_sil
  824.             add edx,ebx
  825.             cmp edx,ebp
  826.             jb stamp
  827.             sub edx,ebp
  828.             stosb
  829.             jmp stamp
  830. end_sil:    
  831.           endm
  832.           
  833. blitsound macro
  834.             ; ecx = ctr
  835.             mov edx,0
  836. zound:      mov ebx,0
  837.             mov eax,0
  838. interp:     add al,[esi]
  839.             adc ah,0
  840.             inc esi
  841.             inc ebx
  842.             dec ecx
  843.             je end_data
  844.             add edx,voc_rate
  845.             cmp edx,play_rate
  846.             jb interp
  847. end_data:   sub edx,play_rate
  848.             div bl
  849.             mov al,[eax + voc_table]
  850.             stosb
  851.             cmp ecx,0
  852.             jne zound
  853.             endm
  854.             
  855.           
  856. VocPackets  dd offset voc_end, offset voc_data, offset voc_cont
  857.             dd offset quiet, offset marker, offset ascii
  858.             dd offset rep_start, offset rep_end, offset extend
  859. decoder: mov ebx,0
  860. decode:  lodsd
  861.         mov bl,al
  862.         cmp al,9
  863.         jnb voc_end
  864.         jmp [ebx*4+ VocPackets]
  865.  
  866. rep_end: mov al,1 ; rep end without rep_start if it is not matched
  867. voc_end: ret
  868.  
  869. rep_start:
  870.         lodsw
  871.         push esi ; inserisci puntatore
  872. reploop:
  873.         mov esi,[esp]  ; ricarica puntatore
  874.         push eax
  875.         call decode
  876.         pop eax
  877.         dec ax
  878.         jne reploop
  879.         add esp,4 ; rimuovi puntatore        
  880.         jmp decode
  881.         
  882. voc_data:
  883.         mov ecx,-2
  884.         shr eax,8
  885.         add ecx,eax
  886.         set_sample
  887.         set_comp
  888. sblit:
  889.         blitsound
  890.         jmp decoder
  891.         
  892. voc_cont:
  893.         shr eax,8
  894.         mov ecx,eax
  895.         jmp sblit
  896.         
  897. quiet:
  898.         movzx eax, word ptr [esi]
  899.         mov ecx,1
  900.         add esi,2
  901.         add ecx,eax
  902.         set_sample
  903.         blitquiet
  904.         jmp decoder
  905.         
  906. extend: mov al,3 ; extended voc file
  907.         ret        
  908.         
  909. marker:
  910.         add esi,2
  911.         jmp decode
  912.         
  913. ascii:
  914.         shr eax,8
  915.         add esi,eax
  916.         jmp decode
  917.         
  918. vocstamp db 'Creative Voice File',1Ah
  919.  
  920.         public _Voc2RAW
  921. _Voc2RAW:
  922.         ; in:
  923.         ; esi = .VOC data to translate, edi = destination for RAW data        
  924.         ; al = error code (0 == no errors)
  925.         ; ebx = RAW datablock
  926.         ; edi = end of RAW datablock + 1
  927.         push edi ; save data start
  928.         add edi,4
  929.         movzx ebx,word ptr [esi+14h]
  930.         mov edx,esi
  931.         mov ecx,0
  932.         add esi,ebx        
  933.         mov ebx, offset  vocstamp
  934. votest: mov eax,[edx]
  935.         cmp eax,[ebx]
  936.         jne eend
  937.         add edx,4
  938.         add ebx,4
  939.         inc ecx
  940.         jmp votest
  941. eend:   cmp ecx,5
  942.         jne novoc
  943.         call decoder
  944.         pop ebx ; restore data start
  945.         sub edi,ebx
  946.         sub edi,4
  947.         mov [ebx],edi
  948.         ; al is zero (value transmitted from decoder)
  949.         ret                
  950. novoc:
  951.         add esp,4 ; remove pointer to start of voc file
  952.         mov al,4 ; not a voc file
  953.         ret        
  954.  
  955. code32  ends
  956.  
  957. code16 segment para public use16
  958.        assume cs:code16,ds:code32
  959.        ; here comes the 16-bit handlers for irq0 and irq1
  960.        ; (to support bimodal irqs without wasteful callbacks)
  961.        
  962. ; RAW KEYBOARD
  963. ; 16bit section, Keyboard ISR for raw keyboard input
  964.  
  965. IRQ1_RISR: ;Real mode ISR
  966.         ; WARNING! BE SURE 386Video IS LINKED IMMEDIATLY AFTER
  967.         ; 386Power (to be sure all the var accessed are into a 64k range)
  968.         ; OR STRANGE THINGS MAY HAPPEN!!!!!!!
  969.         ; (depending on what assembler you use to assemble this stuff)
  970.         push    eax
  971.         push    ebx
  972.         push    ds
  973.         mov     ax,seg code32
  974.         mov     ds,ax
  975.         
  976.     in      al,60h          ; get scan code
  977.  
  978.         movzx   ebx,al          ; move scan code to index register
  979.  
  980.     in      al,61h          ; get control code
  981.         push    eax
  982.     or      al,80h          ; clear keyboard of interrupt:
  983.     out     61h,al          ;
  984.         pop     eax             ;   first send control byte with inverted MSB
  985.     out     61h,al          ;   then send plain control byte
  986.  
  987.         mov     al,EOI          ; send generic EOI to
  988.         
  989.         out     PIC0_CTRL,al    ;   PIC
  990.                 ; enabling other interrupts
  991.         mov al,bl
  992.         and bl,07Fh ; remove flag bit
  993.     ; if the key was released, the high bit is set in the scan code
  994.         mov byte ptr ds:[ebx+offset _RKB],02h ; reset "Is being pressed" flag
  995.                                               ; and left set "Has been pressed"
  996.         
  997.         rol al,1           ;
  998.         jc  rkey_released  ;
  999.         mov byte ptr ds:[ebx+offset _RKB],03h ; set "Is being pressed" flag
  1000.                                               ; and "Has been pressed" flag
  1001. rkey_released:
  1002.         mov ds:_RKBPressed,1     ; state of keyboard has changed
  1003.         pop ds
  1004.         pop ebx
  1005.         pop eax
  1006.         iret
  1007.  
  1008. ; PWM SOUND SPEAKER DRIVER
  1009.  
  1010.  rdont_buzz:
  1011.         cmp Buzzing,0
  1012.         je rgetoutsound
  1013.         mov Buzzing,0
  1014.         ; turn speaker OFF
  1015.         in      al, 61h                 ;Read I/O port B into AL
  1016.         and     al, 11111100b           ;mask lower two bits
  1017.         out     61h, al                 ;to turn off speaker
  1018.         jmp rgetoutsound
  1019.  
  1020. RDoTheSound macro
  1021.         cmp _SoundOn,0
  1022.         je  rdont_buzz    ; no sound if sound flag is off
  1023.         cmp _SoundLen,0
  1024.         je  rdont_buzz    ; no sound if at end of "soundtrack"
  1025.         dec _SoundLen    ; decrease "soundtrack" lenght
  1026.  
  1027.         mov     ebx,_SoundPtr    ;get current count pointer
  1028.         inc     _SoundPtr        ; increase pointer
  1029.         mov     eax,ebx
  1030.         shr     ebx,4
  1031.         and     ax,0Fh
  1032.         add     bx,seg code32
  1033.         mov     es,bx
  1034.         mov     al,es:[ebx]            ; count into AX
  1035.  
  1036.         or      al,al         ; zero count sets speaker off
  1037.         ;je      rdont_buzz    ;
  1038.         mov     ah,al         ;
  1039.         
  1040.         mov     al,P_SET2S
  1041.         out     PIT_CTRL,al      
  1042.  
  1043.  
  1044.         mov     al,ah
  1045.         out     PIT2, al             
  1046.  
  1047.         cmp Buzzing,0
  1048.         jne rgetoutsound
  1049.         mov Buzzing,1
  1050.         ; turn sound on
  1051.         in      al, 61h                 ;read I/O port B into AL
  1052.         or      al,3                    ;turn on bits 0 and 1
  1053.         out     61h,al                  ;to turn on speaker
  1054. rgetoutsound:
  1055.         endm
  1056.         
  1057. ; IRQ0 Timer handler, it handles TWO different "time driven" nested loops
  1058. ; the 8008 Hz PWM sound sytem
  1059. ; the 18,2 Hz System tick for periodic events and rough time keeping
  1060.  
  1061. IRQ0_RISR: 
  1062.         push    eax
  1063.         push    ebx
  1064.         push    ecx
  1065.         push    edx
  1066.     push    ds
  1067.         push    es
  1068.         mov     ax,code32
  1069.         mov     ds,ax
  1070.         mov ebx,play_rate
  1071.         add _TimerTicks,ebx
  1072.         add  InnerTicks,ebx
  1073.         add    SecTicks,ebx
  1074.         RDoTheSound
  1075.         sti
  1076.         mov eax,SecTicks
  1077.         sub eax,TIMERTICK
  1078.         jb rdone_sec
  1079.         mov SecTicks,eax
  1080.         inc _Seconds
  1081. rdone_sec:        
  1082.         
  1083.         mov eax,InnerTicks
  1084.         sub eax,TIMERTICK
  1085.         jb rdone_irq0
  1086.         mov InnerTicks,eax
  1087.         ; n.b. TTick conta i ticks di sistema in formato fixed point
  1088.         ;      con una cifra decimale
  1089.         inc _SysTicks
  1090. rzapped_time:
  1091.         ; it's time to call the old ISR
  1092.         pushf
  1093.         call dword ptr cs:[(8*4) + offset _OldInt]
  1094.         jmp short rirq0_digged
  1095. rdone_irq0:        
  1096.         mov al,EOI
  1097.         out PIC0_CTRL,al
  1098. rirq0_digged:    
  1099.         pop es    
  1100.         pop ds
  1101.         pop edx
  1102.         pop ecx
  1103.         pop ebx
  1104.         pop eax
  1105.         iret ; ritorna il controllo a 386 power
  1106.         
  1107. PFLP_RISR: 
  1108.         push    eax
  1109.         push    ebx
  1110.     push    ds
  1111.         mov     ax,code32
  1112.         mov     ds,ax
  1113.         mov ebx,FrameTicks
  1114.         add _TimerTicks,ebx
  1115.         add  InnerTicks,ebx
  1116.         add    SecTicks,ebx
  1117.         sti
  1118.         mov eax,SecTicks
  1119.         sub eax,ONESECOND
  1120.         jb prdone_sec
  1121.         mov SecTicks,eax
  1122.         inc _Seconds
  1123. prdone_sec:        
  1124.         
  1125.         mov eax,InnerTicks
  1126.         sub eax,TIMERTICK
  1127.         jb prdone_irq0
  1128.         mov InnerTicks,eax
  1129.         ; n.b. TTick conta i ticks di sistema in formato fixed point
  1130.         ;      con una cifra decimale
  1131.         inc _SysTicks
  1132. przapped_time:
  1133.         ; it's time to call the old ISR
  1134.         pushf
  1135.         call dword ptr cs:[(8*4) + offset _OldInt]
  1136.         jmp short prirq0_digged
  1137. prdone_irq0:        
  1138.         mov al,EOI
  1139.         out PIC0_CTRL,al
  1140. prirq0_digged:    
  1141.         pop ds
  1142.         pop ebx
  1143.         pop eax
  1144.         iret ; ritorna il controllo a 386 power
  1145.        
  1146. code16 ends
  1147.  
  1148.     END
  1149.